<template>
  <div class="app-container">
    <!-- 搜索工具栏 -->
    <div class="search-wrapper">
      <el-form :model="queryParams" ref="queryFormRef" inline>
        <el-form-item label="表名称" prop="tableName">
          <el-input
                  v-model="queryParams.tableName"
                  placeholder="请输入表名称"
                  clearable
                  @keyup.enter="handleQuery"
          />
        </el-form-item>
        <el-form-item>
          <el-button type="primary" @click="handleQuery">搜索</el-button>
          <el-button @click="resetQuery">重置</el-button>
        </el-form-item>
      </el-form>
    </div>
    <el-card>
      <!-- 操作按钮区域 -->
      <template #header>
        <div class="card-header">
          <ButtonGroup>
            <el-button type="primary" icon="Download" @click="handleGenCode"
            >生成代码</el-button
            >

            <el-button type="info" icon="Upload" @click="openImportTable"
            >导入表结构</el-button
            >

            <el-button
                    type="danger"
                    icon="Delete"
                    @click="handleBatchDelete"
                    :disabled="!ids.length"
            >批量删除</el-button
            >
          </ButtonGroup>
        </div>
      </template>

      <!-- 数据表格 -->
      <el-table
              v-loading="loading"
              :data="tableList"
              @selection-change="handleSelectionChange"
      >
        <el-table-column type="selection" align="center" width="55" />
        <el-table-column
                label="表名称"
                align="center"
                prop="tableName"
                :show-overflow-tooltip="true"
        />
        <el-table-column
                label="表描述"
                align="center"
                prop="tableComment"
                :show-overflow-tooltip="true"
        />
        <el-table-column label="创建时间" align="center" prop="createTime" />
        <el-table-column
                label="操作"
                align="center"
                class-name="small-padding fixed-width"
        >
          <template #default="{ row }">
            <el-button
                    type="success"
                    icon="View"
                    link
                    @click="handlePreview(row)"
            >预览</el-button
            >
            <el-button
                    type="danger"
                    link
                    icon="Delete"
                    @click="handleDelete(row)"
            >删除</el-button
            >
            <el-button
                    type="info"
                    link
                    icon="Refresh"
                    @click="handleSynchDb(row)"
            >同步</el-button
            >
          </template>
        </el-table-column>
      </el-table>

      <div class="pagination-container">
        <el-pagination
                background
                v-model:current-page="queryParams.pageNum"
                v-model:page-size="queryParams.pageSize"
                :total="total"
                :page-sizes="[10, 20, 30, 50]"
                layout="total, sizes, prev, pager, next, jumper"
                @size-change="handleSizeChange"
                @current-change="handleCurrentChange"
        />
      </div>
      <!-- 预览界面 -->
      <el-dialog
              v-model="preview.open"
              :title="preview.title"
              width="80%"
              top="5vh"
              append-to-body
              @close="handlePreviewClose"
      >
        <el-tabs v-model="preview.activeName">
          <el-tab-pane
                  v-for="(value, key) in preview.data"
                  :key="key"
                  :label="key"
                  :name="key"
          >
            <div class="code-preview-wrapper">
              <div class="code-preview-header">
                <el-button
                        type="primary"
                        link
                        icon="CopyDocument"
                        @click="handleCopyCode(value)"
                >复制代码</el-button
                >
              </div>
              <pre><code v-html="highlightedCode(value)"></code></pre>
            </div>
          </el-tab-pane>
        </el-tabs>
      </el-dialog>

      <!-- 导入表 -->
      <el-dialog
              v-model="import_visible"
              :title="import_title"
              width="800px"
              top="5vh"
      >
        <!-- 添加搜索框 -->
        <el-form :model="dbTableParams" ref="dbQueryFormRef" inline>
          <el-form-item label="表名称" prop="tableName">
            <el-input
                    v-model="dbTableParams.tableName"
                    placeholder="请输入表名称"
                    clearable
                    @keyup.enter="handleDbTableSearch"
            />
          </el-form-item>
          <el-form-item label="表描述" prop="tableComment">
            <el-input
                    v-model="dbTableParams.tableComment"
                    placeholder="请输入表描述"
                    clearable
                    @keyup.enter="handleDbTableSearch"
            />
          </el-form-item>
          <el-form-item>
            <el-button @click="resetDbTableSearch">重置</el-button>
            <el-button type="primary" @click="handleDbTableSearch"
            >搜索</el-button
            >
          </el-form-item>
        </el-form>

        <!-- 修改表格选择方式 -->
        <el-table
                ref="dbTableRef"
                v-loading="dbTableLoading"
                :data="dbTableList"
                @selection-change="handleDbTableSelectionChange"
                height="350px"
        >
          <el-table-column type="selection" align="center" width="55" />
          <el-table-column
                  label="表名称"
                  align="center"
                  prop="tableName"
                  :show-overflow-tooltip="true"
          />
          <el-table-column
                  label="表描述"
                  align="center"
                  prop="tableComment"
                  :show-overflow-tooltip="true"
          />
          <el-table-column label="创建时间" align="center" prop="createTime" />
          <el-table-column label="更新时间" align="center" prop="updateTime" />
        </el-table>

        <div class="pagination-container">
          <el-pagination
                  background
                  v-model:current-page="dbTableParams.pageNum"
                  v-model:page-size="dbTableParams.pageSize"
                  :total="dbTableTotal"
                  :page-sizes="[10, 20, 30, 50]"
                  layout="total, sizes, prev, pager, next, jumper"
                  @size-change="handleDbTableSizeChange"
                  @current-change="handleDbTableCurrentChange"
          />
        </div>

        <template #footer>
          <div class="dialog-footer">
            <el-button @click="closeImport">取 消</el-button>
            <el-button
                    type="primary"
                    @click="submitImport"
                    :disabled="!dbTableSelection.length"
            >确 定</el-button
            >
          </div>
        </template>
      </el-dialog>
    </el-card>
  </div>
</template>

<script lang="ts" setup>
  import { ElMessage, ElMessageBox } from "element-plus";
  import {
    listTableApi,
    previewTableApi,
    delTableApi,
    downloadCodeApi,
    synchDbApi,
    listDbTableApi,
    importTableApi,
  } from "@/api/tool/gen";
  import hljs from "highlight.js";
  import "highlight.js/styles/github.css";
  import { saveAs } from 'file-saver'
  // refs
  const queryFormRef = ref();
  const dbQueryFormRef = ref();
  const dbTableRef = ref();

  // 数据
  const loading = ref(false);
  const ids = ref<string[]>([]);
  const total = ref(0);
  const tableList = ref([]);

  const queryParams = reactive({
    pageNum: 1,
    pageSize: 10,
    tableName: undefined,
  });

  const preview = reactive({
    open: false,
    title: "代码预览",
    data: {},
    activeName: "entity.java",
  });

  const import_visible = ref(false);
  const import_title = ref("导入表");
  const dbTableList = ref([]);
  const dbTableTotal = ref(0);
  const dbTableLoading = ref(false);
  const dbTableSelection = ref<any[]>([]);

  const dbTableParams = reactive({
    pageNum: 1,
    pageSize: 10,
    tableName: undefined,
    tableComment: undefined,
  });

  // 添加代码高亮缓存
  const codeCache = new Map();

  // 方法
  const getList = async () => {
    try {
      loading.value = true;
      const { data } = await listTableApi(queryParams);
      tableList.value = data.rows;
      total.value = data.total;
    } catch (error) {
    } finally {
      loading.value = false;
    }
  };

  const handleQuery = () => {
    queryParams.pageNum = 1;
    getList();
  };

  const resetQuery = () => {
    queryFormRef.value?.resetFields();
    handleQuery();
  };

  const handleSizeChange = (val: number) => {
    queryParams.pageSize = val;
    getList();
  };

  const handleCurrentChange = (val: number) => {
    queryParams.pageNum = val;
    getList();
  };

  const handlePreview = async (row: any) => {
    try {
      const { data } = await previewTableApi(row.tableId);
      preview.data = data;
      preview.open = true;
    } catch (error) {}
  };

  // 优化后的代码高亮方法
  const highlightedCode = (code: string) => {
    if (!code || !preview.open) return "";

    // 生成缓存key
    const cacheKey = `${preview.activeName}-${code}`;

    // 如果缓存中存在，直接返回缓存的结果
    if (codeCache.has(cacheKey)) {
      return codeCache.get(cacheKey);
    }

    let result = "";
    const language = preview.activeName.split(".").pop()?.toLowerCase() || "";

    try {
      // 根据文件扩展选择语言
      const languageMap = {
        vue: "html",
        html: "html",
        java: "java",
        xml: "xml",
        sql: "sql",
        js: "javascript",
        ts: "typescript",
      };

      const lang =
              languageMap[language as keyof typeof languageMap] || "plaintext";
      result = hljs.highlight(code, { language: lang }).value;

      // 存入缓存
      codeCache.set(cacheKey, result);
      return result;
    } catch (error) {
      console.error("代码高亮失败:", error);
      return code;
    }
  };

  const handleGenCode = async () => {
    if (!ids.value.length) {
      ElMessage.warning("请选择要生成的表");
      return;
    }
    // try {
    //   const tableNames = tableList.value
    //     .filter((item: any) => ids.value.includes(item.tableId))
    //     .map((item: any) => item.tableName)
    //     .join(",");
    //   const response = await downloadCodeApi(tableNames);
    //   const blob = new Blob([response.data], {
    //         type: "application/zip",
    //   });
    //   saveAs(blob, "code.zip");
    //   ElMessage.success("生成成功");
    // } catch (error) {}
  };

  const handleSynchDb = async (row: any) => {
    try {
      await ElMessageBox.confirm(
              `确认要强制同步"${row.tableName}"表结构吗？`,
              "警告",
              {
                confirmButtonText: "确定",
                cancelButtonText: "取消",
                type: "warning",
              }
      );
      await synchDbApi(row.tableName);
      ElMessage.success("同步成功");
    } catch (error) {
      if (error !== "cancel") ElMessage.error("同步失败");
    }
  };

  const openImportTable = () => {
    import_visible.value = true;
    Object.assign(dbTableParams, {
      pageNum: 1,
      pageSize: 10,
      tableName: undefined,
      tableComment: undefined,
    });
    getDbTableList();
  };

  const closeImport = () => {
    import_visible.value = false;
    dbTableList.value = [];
    dbTableSelection.value = [];
    dbTableRef.value?.clearSelection();
  };

  const getDbTableList = async () => {
    try {
      dbTableLoading.value = true;
      const { data } = await listDbTableApi(dbTableParams);
      dbTableList.value = data.rows;
      dbTableTotal.value = data.total;
    } catch (error) {
    } finally {
      dbTableLoading.value = false;
    }
  };

  const handleDbTableSearch = () => {
    dbTableParams.pageNum = 1;
    getDbTableList();
  };

  const handleDbTableSizeChange = (val: number) => {
    dbTableParams.pageSize = val;
    getDbTableList();
  };

  const handleDbTableCurrentChange = (val: number) => {
    dbTableParams.pageNum = val;
    getDbTableList();
  };

  const resetDbTableSearch = () => {
    dbQueryFormRef.value?.resetFields();
    Object.assign(dbTableParams, {
      pageNum: 1,
      pageSize: 10,
      tableName: undefined,
      tableComment: undefined,
    });
    handleDbTableSearch();
  };

  const handleDbTableSelectionChange = (selection: any[]) => {
    dbTableSelection.value = selection;
  };

  const submitImport = async () => {
    if (!dbTableSelection.value.length) {
      ElMessage.warning("请选择要导入的表");
      return;
    }

    try {
      const tables = dbTableSelection.value.map((row: any) => row.tableName);
      await importTableApi(tables);
      ElMessage.success("导入成功");
      closeImport();
      getList();
    } catch (error) {}
  };

  const handleSelectionChange = (selection: any[]) => {
    ids.value = selection.map((item) => item.tableId);
  };

  const handleCopyCode = async (code: string) => {
    try {
      await navigator.clipboard.writeText(code);
      ElMessage.success("复制成功");
    } catch (error) {}
  };

  // 修改预览关闭处理方法
  const handlePreviewClose = () => {
    preview.data = {};
    preview.activeName = "entity.java";
    // 清空缓存
    codeCache.clear();
  };

  // 添加 tab 切换处理法
  const handleTabChange = () => {
    // 可以在这里做一些优化，比如预加载下一个 tab 的内容
  };

  // 添加删除方法
  const handleDelete = async (row: any) => {
    try {
      await ElMessageBox.confirm(`确认要删除表"${row.tableName}"吗？`, "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      });
      await delTableApi(row.tableId);
      ElMessage.success("删除成功");
      getList();
    } catch (error) {}
  };

  // 生命周期
  onMounted(() => {
    getList();
  });

  // 批量删除
  const handleBatchDelete = async () => {
    if (!ids.value.length) {
      ElMessage.warning("请选择要删除的表");
      return;
    }

    try {
      await ElMessageBox.confirm("确认要删除选中的表吗？", "警告", {
        confirmButtonText: "确定",
        cancelButtonText: "取消",
        type: "warning",
      });

      await delTableApi(ids.value.join(","));
      ElMessage.success("删除成功");
      getList();
      ids.value = [];
    } catch (error) {}
  };
</script>

<style scoped>
  .hljs {
    padding: 15px;
    border-radius: 5px;
    background-color: #f5f5f5;
  }

  .el-dialog :deep(.el-table) {
    margin: 10px 0;
  }

  .mb8 {
    margin-bottom: 8px;
  }

  /* 添加代码高亮相关样式 */
  pre {
    margin: 0;
    padding: 16px;
    overflow: auto;
    font-size: 14px;
    line-height: 1.5;
    background-color: #f6f8fa;
    border-radius: 6px;
  }

  code {
    font-family: Consolas, Monaco, "Andale Mono", "Ubuntu Mono", monospace;
    white-space: pre;
    word-spacing: normal;
    word-break: normal;
    word-wrap: normal;
  }

  /* 引入指定的highlight.js样式 */
  :deep(.hljs) {
    background: #f6f8fa;
    color: #24292e;
  }

  :deep(.hljs-keyword) {
    color: #d73a49;
  }

  :deep(.hljs-string) {
    color: #032f62;
  }

  :deep(.hljs-comment) {
    color: #6a737d;
  }

  :deep(.hljs-function) {
    color: #6f42c1;
  }

  :deep(.hljs-number) {
    color: #005cc5;
  }

  :deep(.hljs-operator) {
    color: #d73a49;
  }

  :deep(.hljs-class) {
    color: #6f42c1;
  }

  :deep(.hljs-attr) {
    color: #005cc5;
  }

  :deep(.hljs-built_in) {
    color: #6f42c1;
  }

  :deep(.hljs-property) {
    color: #005cc5;
  }

  :deep(.hljs-variable) {
    color: #24292e;
  }

  :deep(.hljs-title) {
    color: #6f42c1;
  }

  /* 修改代码预览区域样式 */
  .code-preview-wrapper {
    height: 500px;
    overflow-y: auto;
    background-color: #f6f8fa;
    border-radius: 6px;
    display: flex;
    flex-direction: column;
  }

  pre {
    margin: 0;
    flex: 1;
    overflow: auto;
  }

  /* 添加代码预览头部样式 */
  .code-preview-header {
    padding: 8px 16px;
    background-color: #f6f8fa;
    border-bottom: 1px solid #e1e4e8;
    display: flex;
    justify-content: flex-end;
  }

  /* 自定义滚动条样式 */
  .code-preview-wrapper::-webkit-scrollbar {
    width: 6px;
    height: 6px;
  }

  .code-preview-wrapper::-webkit-scrollbar-thumb {
    background: #ccc;
    border-radius: 3px;
  }

  .code-preview-wrapper::-webkit-scrollbar-track {
    background: #f1f1f1;
    border-radius: 3px;
  }
</style>
